/*
 * @Author: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git
 * @Date: 2025-07-07 10:31:38
 * @LastEditors: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git
 * @LastEditTime: 2025-07-09 13:55:50
 * @FilePath: /lesson/lesson_net/http/Http.hpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#pragma once

#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
#include <sstream>
const static std::string base_sep = "\r\n";
const static std::string line_sep = ": ";
const static std::string prefixpath = "wwwroot"; // web根目录
const static std::string homepage = "index.html";
const static std::string httpversion = "HTTP/1.0";
const static std::string spacesep = " ";
const static std::string suffixsep = ".";
const static std::string html_404 = "404.html";
const static std::string arg_sep = "?";

class HttpRequest
{

private:
    // 基本的http请求格式
    std::string _req_line;
    std::vector<std::string> _req_headers;
    std::string _blank_line;
    std::string _body_text;

    // 更具体的属性字段，需要进一步反序列化
    std::string _method;
    std::string _url;
    std::string _version;

    std::unordered_map<std::string, std::string> _headers_kv;

private:
    // 1、按行读取：提取每一行的函数
    std::string GetLine(std::string &reqstr)
    {
        auto pos = reqstr.find(base_sep);
        if (pos == std::string::npos)
            return std::string();                       // 如果没找到就返回 空串
        std::string line = reqstr.substr(0, pos);       // 提取当前行 赋值到line
        reqstr.erase(0, line.size() + base_sep.size()); // 直接删除当前行

        return line.empty() ? base_sep : line;
    }

    // 2.1 详细处理请求行的函数
    void ParseReqLine()
    {
        // 把请求行字符串 写到流里面去
        std::stringstream ss(_req_line); // 这个stringstream对象相当于cin
        ss >> _method >> _url >> _version;
    }
    // 2.2 详细处理请求报头的函数
    void ParseReqHeader()
    {
        for (auto &header : _req_headers)
        {
            auto pos = header.find(line_sep);
            if (pos == std::string::npos)
                continue;
            std::string k = header.substr(0, pos);
            std::string v = header.substr(pos + line_sep.size());
            if (k.empty() || v.empty())
                continue;

            _headers_kv.insert(std::make_pair(k, v));
        }
    }

public:
    HttpRequest() : _blank_line(base_sep) // 4、在初始化的时候直接处理了“空行”
    {
    }
    void Deserialize(std::string &reqstr)
    {
        // (1)基本的反序列化
        _req_line = GetLine(reqstr); // 1、“请求行”已经处理完了
        std::string header;          // 2、处理“请求报头”
        do
        {
            header = GetLine(reqstr);
            if (header.empty())
                break;
            else if (header == base_sep)
                break;
            else
                _req_headers.push_back(header);

        } while (true);

        // 3、处理“请求正文”
        if (!reqstr.empty())
        {
            _body_text = reqstr;
        }

        // (2)进一步反序列化
        ParseReqLine();
        ParseReqHeader();
    }

    // 打印测试：
    void TestPrint()
    {
        std::cout << "###" << _req_line << std::endl;
        for (auto &header : _req_headers)
        {
            std::cout << "@@@" << header << std::endl;
        }
        std::cout << "***" << _blank_line << std::endl;
        std::cout << "$$$" << _body_text << std::endl;

        std::cout << "Method->" << _method << std::endl;
        std::cout << "Url->" << _url << std::endl;
        std::cout << "Version->" << _version << std::endl;

        for (auto &header_kv : _headers_kv)
        {
            std::cout << "!!!" << header_kv.first << "->" << header_kv.second << std::endl;
        }
    }
    ~HttpRequest()
    {
    }
};

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

class HttpResponse
{

private:
    // httpresponse 具体 属性(微观)
    std::string _version;
    int _status_code;
    std::string _desc;
    std::unordered_map<std::string, std::string> _headers_kv;

    // http宏观格式
    std::string _status_line;
    std::vector<std::string> _resp_headers;
    std::string _blank_line;
    std::string _resp_body_text;

public:
    // 构造函数
    HttpResponse()
        : _version(httpversion), _blank_line(base_sep) // 空行直接在这里构造赋值
    {
    }

    void AddCode(int code, std::string &desc)
    {
        _status_code = code;
        _desc = desc;
    }
    void AddHeader(const std::string k, const std::string v)
    {
        _headers_kv[k] = v;
    }

    void AddBodyText(const std::string body_text)
    {
        _resp_body_text = body_text;
    }

    // 对响应：序列化
    std::string Serialize()
    {
        // 1、构建状态行
        _status_line = _version + spacesep + std::to_string(_status_code) + spacesep + _desc + base_sep;
        // 2、构建响应报头
        for (auto &headers : _headers_kv)
        {
            std::string headers_line = headers.first + line_sep + headers.second + base_sep;
            _resp_headers.push_back(headers_line);
        }

        // 3、空行和响应正文
        // 4、正式序列化(直接把所有，构建好的东西，拼成一个字符串返回！)
        std::string responseStr = _status_line;
        for (auto &line : _resp_headers)
        {
            responseStr += line;
        }
        responseStr += _blank_line;
        responseStr += _resp_body_text;

        return responseStr;
    }
    // 析构
    ~HttpResponse()
    {
    }
};

class HttpServer
{
public:
    HttpServer() {}

    std::string HandlerHttpRequest(std::string &reqstr)
    {
#ifdef TEST
        std::cout << "--------------------------" std::endl;
        std::cout << req;

        std::string responsestr = "HTTP/1.1 200 ok \r\n";
        return responsestr;
#else
        HttpRequest req;
        req.Deserialize(reqstr);
        req.TestPrint();

        return std::string();
#endif
    }

    ~HttpServer() {}
};
